# coding: utf-8

# Copyright (C) 2014 by Ronnie Sahlberg<ronniesahlberg@gmail.com>
# Copyright (C) 2015 by Markus Rosjat<markus.rosjat@gmail.com>
# SPDX-FileCopyrightText: 2014 The python-scsi Authors
#
# SPDX-License-Identifier: LGPL-2.1-or-later

from pyscsi.utils.converter import decode_bits

#
# SPC4 4.5 Sense Data
#
SENSE_FORMAT_CURRENT_FIXED = 0x70
SENSE_FORMAT_DEFERRED_FIXED = 0x71
SENSE_FORMAT_CURRENT_DESCRIPTOR = 0x72
SENSE_FORMAT_DEFERRED_DESCRIPTOR = 0x73

# dict with common key code qualifiers
sense_key_dict = {
    0x00: "No Sense",
    0x01: "Recovered Error",
    0x02: "Not Ready",
    0x03: "Medium Error",
    0x04: "Hardware Error",
    0x05: "Illegal Request",
    0x06: "Unit Attention",
    0x07: "Data Protect",
    0x08: "Blank Check",
    0x09: "Vendor Specific",
    0x0A: "Copy Aborted",
    0x0B: "Aborted Command",
    0x0D: "Volume Overflow",
    0x0E: "Miscompare",
    0x0F: "Completed",
}

vendor_specific_sense_asc = vendor_specific_sense_ascq = range(0x80, 0xFF + 1)

# dict with additional sense data
sense_ascq_dict = {
    0x0001: "FILEMARK DETECTED",
    0x0002: "END-OF-PARTITION/MEDIUM DETECTED",
    0x0003: "SETMARK DETECTED",
    0x0004: "BEGINNING-OF-PARTITION/MEDIUM DETECTED",
    0x0005: "END-OF-DATA DETECTED",
    0x0006: "I/O PROCESS TERMINATED",
    0x0007: "PROGRAMMABLE EARLY WARNING DETECTED",
    0x0011: "AUDIO PLAY OPERATION IN PROGRESS",
    0x0012: "AUDIO PLAY OPERATION PAUSED",
    0x0013: "AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED",
    0x0014: "AUDIO PLAY OPERATION STOPPED DUE TO ERROR",
    0x0015: "NO CURRENT AUDIO STATUS TO RETURN",
    0x0016: "OPERATION IN PROGRESS",
    0x0017: "CLEANING REQUESTED",
    0x0018: "ERASE OPERATION IN PROGRESS",
    0x0019: "LOCATE OPERATION IN PROGRESS",
    0x001A: "REWIND OPERATION IN PROGRESS",
    0x001B: "SET CAPACITY OPERATION IN PROGRESS",
    0x001C: "VERIFY OPERATION IN PROGRESS",
    0x001D: "ATA PASS THROUGH INFORMATION AVAILABLE",
    0x001E: "CONFLICTING SA CREATION REQUEST",
    0x001F: "LOGICAL UNIT TRANSITIONING TO ANOTHER POWER CONDITION",
    0x0020: "EXTENDED COPY INFORMATION AVAILABLE",
    0x0021: "ATOMIC COMMAND ABORTED DUE TO ACA",
    0x0100: "NO INDEX/SECTOR SIGNAL",
    0x0200: "NO SEEK COMPLETE",
    0x0300: "PERIPHERAL DEVICE WRITE FAULT",
    0x0301: "NO WRITE CURRENT",
    0x0302: "EXCESSIVE WRITE ERRORS",
    0x0400: "LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE",
    0x0401: "LOGICAL UNIT IS IN PROCESS OF BECOMING READY",
    0x0402: "LOGICAL UNIT NOT READY, INITIALIZING COMMAND REQUIRED",
    0x0403: "LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED",
    0x0404: "LOGICAL UNIT NOT READY, FORMAT IN PROGRESS",
    0x0405: "LOGICAL UNIT NOT READY, REBUILD IN PROGRESS",
    0x0406: "LOGICAL UNIT NOT READY, RECALCULATION IN PROGRESS",
    0x0407: "LOGICAL UNIT NOT READY, OPERATION IN PROGRESS",
    0x0408: "LOGICAL UNIT NOT READY, LONG WRITE IN PROGRESS",
    0x0409: "LOGICAL UNIT NOT READY, SELF-TEST IN PROGRESS",
    0x040A: "LOGICAL UNIT NOT ACCESSIBLE, ASYMMETRIC ACCESS STATE TRANSITION",
    0x040B: "LOGICAL UNIT NOT ACCESSIBLE, TARGET PORT IN STANDBY STATE",
    0x040C: "LOGICAL UNIT NOT ACCESSIBLE, TARGET PORT IN UNAVAILABLE STATE",
    0x040D: "LOGICAL UNIT NOT READY, STRUCTURE CHECK REQUIRED",
    0x040E: "LOGICAL UNIT NOT READY, SECURITY SESSION IN PROGRESS",
    0x0410: "LOGICAL UNIT NOT READY, AUXILIARY MEMORY NOT ACCESSIBLE",
    0x0411: "LOGICAL UNIT NOT READY, NOTIFY (ENABLE SPINUP) REQUIRED",
    0x0412: "LOGICAL UNIT NOT READY, OFFLINE",
    0x0413: "LOGICAL UNIT NOT READY, SA CREATION IN PROGRESS",
    0x0414: "LOGICAL UNIT NOT READY, SPACE ALLOCATION IN PROGRESS",
    0x0415: "LOGICAL UNIT NOT READY, ROBOTICS DISABLED",
    0x0416: "LOGICAL UNIT NOT READY, CONFIGURATION REQUIRED",
    0x0417: "LOGICAL UNIT NOT READY, CALIBRATION REQUIRED",
    0x0418: "LOGICAL UNIT NOT READY, A DOOR IS OPEN",
    0x0419: "LOGICAL UNIT NOT READY, OPERATING IN SEQUENTIAL MODE",
    0x041A: "LOGICAL UNIT NOT READY, START STOP UNIT COMMAND IN PROGRESS",
    0x041B: "LOGICAL UNIT NOT READY, SANITIZE IN PROGRESS",
    0x041C: "LOGICAL UNIT NOT READY, ADDITIONAL POWER USE NOT YET GRANTED",
    0x041D: "LOGICAL UNIT NOT READY, CONFIGURATION IN PROGRESS",
    0x041E: "LOGICAL UNIT NOT READY, MICROCODE ACTIVATION REQUIRED",
    0x041F: "LOGICAL UNIT NOT READY, MICROCODE DOWNLOAD REQUIRED",
    0x0420: "LOGICAL UNIT NOT READY, LOGICAL UNIT RESET REQUIRED",
    0x0421: "LOGICAL UNIT NOT READY, HARD RESET REQUIRED",
    0x0422: "LOGICAL UNIT NOT READY, POWER CYCLE REQUIRED",
    0x0500: "LOGICAL UNIT DOES NOT RESPOND TO SELECTION",
    0x0600: "NO REFERENCE POSITION FOUND",
    0x0700: "MULTIPLE PERIPHERAL DEVICES SELECTED",
    0x0800: "LOGICAL UNIT COMMUNICATION FAILURE",
    0x0801: "LOGICAL UNIT COMMUNICATION TIME-OUT",
    0x0802: "LOGICAL UNIT COMMUNICATION PARITY ERROR",
    0x0803: "LOGICAL UNIT COMMUNICATION CRC ERROR (ULTRA-DMA/32)",
    0x0804: "UNREACHABLE COPY TARGET",
    0x0900: "TRACK FOLLOWING ERROR",
    0x0901: "TRACKING SERVO FAILURE",
    0x0902: "FOCUS SERVO FAILURE",
    0x0903: "SPINDLE SERVO FAILURE",
    0x0904: "HEAD SELECT FAULT",
    0x0905: "VIBRATION INDUCED TRACKING ERROR",
    0x0A00: "ERROR LOG OVERFLOW",
    0x0B00: "WARNING",
    0x0B01: "WARNING - SPECIFIED TEMPERATURE EXCEEDED",
    0x0B02: "WARNING - ENCLOSURE DEGRADED",
    0x0B03: "WARNING - BACKGROUND SELF-TEST FAILED",
    0x0B04: "WARNING - BACKGROUND PRE-SCAN DETECTED MEDIUM ERROR",
    0x0B05: "WARNING - BACKGROUND MEDIUM SCAN DETECTED MEDIUM ERROR",
    0x0B06: "WARNING - NON-VOLATILE CACHE NOW VOLATILE",
    0x0B07: "WARNING - DEGRADED POWER TO NON-VOLATILE CACHE",
    0x0B08: "WARNING - POWER LOSS EXPECTED",
    0x0B09: "WARNING - DEVICE STATISTICS NOTIFICATION ACTIVE",
    0x0C00: "WRITE ERROR",
    0x0C01: "WRITE ERROR - RECOVERED WITH AUTO REALLOCATION",
    0x0C02: "WRITE ERROR - AUTO REALLOCATION FAILED",
    0x0C03: "WRITE ERROR - RECOMMEND REASSIGNMENT",
    0x0C04: "COMPRESSION CHECK MISCOMPARE ERROR",
    0x0C05: "DATA EXPANSION OCCURRED DURING COMPRESSION",
    0x0C06: "BLOCK NOT COMPRESSIBLE",
    0x0C07: "WRITE ERROR - RECOVERY NEEDED",
    0x0C08: "WRITE ERROR - RECOVERY FAILED",
    0x0C09: "WRITE ERROR - LOSS OF STREAMING",
    0x0C0A: "WRITE ERROR - PADDING BLOCKS ADDED",
    0x0C0B: "AUXILIARY MEMORY WRITE ERROR",
    0x0C0C: "WRITE ERROR - UNEXPECTED UNSOLICITED DATA",
    0x0C0D: "WRITE ERROR - NOT ENOUGH UNSOLICITED DATA",
    0x0C0E: "MULTIPLE WRITE ERRORS",
    0x0C0F: "DEFECTS IN ERROR WINDOW",
    0x0C10: "INCOMPLETE MULTIPLE ATOMIC WRITE OPERATIONS",
    0x0D00: "ERROR DETECTED BY THIRD PARTY TEMPORARY INITIATOR",
    0x0D01: "THIRD PARTY DEVICE FAILURE",
    0x0D02: "COPY TARGET DEVICE NOT REACHABLE",
    0x0D03: "INCORRECT COPY TARGET DEVICE TYPE",
    0x0D04: "COPY TARGET DEVICE DATA UNDERRUN",
    0x0D05: "COPY TARGET DEVICE DATA OVERRUN",
    0x0E00: "INVALID INFORMATION UNIT",
    0x0E01: "INFORMATION UNIT TOO SHORT",
    0x0E02: "INFORMATION UNIT TOO LONG",
    0x0E03: "INVALID FIELD IN COMMAND INFORMATION UNIT",
    0x1000: "ID CRC OR ECC ERROR",
    0x1001: "LOGICAL BLOCK GUARD CHECK FAILED",
    0x1002: "LOGICAL BLOCK APPLICATION TAG CHECK FAILED",
    0x1003: "LOGICAL BLOCK REFERENCE TAG CHECK FAILED",
    0x1004: "LOGICAL BLOCK PROTECTION ERROR ON RECOVER BUFFERED DATA",
    0x1005: "LOGICAL BLOCK PROTECTION METHOD ERROR",
    0x1100: "UNRECOVERED READ ERROR",
    0x1101: "READ RETRIES EXHAUSTED",
    0x1102: "ERROR TOO LONG TO CORRECT",
    0x1103: "MULTIPLE READ ERRORS",
    0x1104: "UNRECOVERED READ ERROR - AUTO REALLOCATE FAILED",
    0x1105: "L-EC UNCORRECTABLE ERROR",
    0x1106: "CIRC UNRECOVERED ERROR",
    0x1107: "DATA RE-SYNCHRONIZATION ERROR",
    0x1108: "INCOMPLETE BLOCK READ",
    0x1109: "NO GAP FOUND",
    0x110A: "MISCORRECTED ERROR",
    0x110B: "UNRECOVERED READ ERROR - RECOMMEND REASSIGNMENT",
    0x110C: "UNRECOVERED READ ERROR - RECOMMEND REWRITE THE DATA",
    0x110D: "DE-COMPRESSION CRC ERROR",
    0x110E: "CANNOT DECOMPRESS USING DECLARED ALGORITHM",
    0x110F: "ERROR READING UPC/EAN NUMBER",
    0x1110: "ERROR READING ISRC NUMBER",
    0x1111: "READ ERROR - LOSS OF STREAMING",
    0x1112: "AUXILIARY MEMORY READ ERROR",
    0x1113: "READ ERROR - FAILED RETRANSMISSION REQUEST",
    0x1114: "READ ERROR - LBA MARKED BAD BY APPLICATION CLIENT",
    0x1115: "WRITE AFTER SANITIZE REQUIRED",
    0x1200: "ADDRESS MARK NOT FOUND FOR ID FIELD",
    0x1300: "ADDRESS MARK NOT FOUND FOR DATA FIELD",
    0x1400: "RECORDED ENTITY NOT FOUND",
    0x1401: "RECORD NOT FOUND",
    0x1402: "FILEMARK OR SETMARK NOT FOUND",
    0x1403: "END-OF-DATA NOT FOUND",
    0x1404: "BLOCK SEQUENCE ERROR",
    0x1405: "RECORD NOT FOUND - RECOMMEND REASSIGNMENT",
    0x1406: "RECORD NOT FOUND - DATA AUTO-REALLOCATED",
    0x1407: "LOCATE OPERATION FAILURE",
    0x1500: "RANDOM POSITIONING ERROR",
    0x1501: "MECHANICAL POSITIONING ERROR",
    0x1502: "POSITIONING ERROR DETECTED BY READ OF MEDIUM",
    0x1600: "DATA SYNCHRONIZATION MARK ERROR",
    0x1601: "DATA SYNC ERROR - DATA REWRITTEN",
    0x1602: "DATA SYNC ERROR - RECOMMEND REWRITE",
    0x1603: "DATA SYNC ERROR - DATA AUTO-REALLOCATED",
    0x1604: "DATA SYNC ERROR - RECOMMEND REASSIGNMENT",
    0x1700: "RECOVERED DATA WITH NO ERROR CORRECTION APPLIED",
    0x1701: "RECOVERED DATA WITH RETRIES",
    0x1702: "RECOVERED DATA WITH POSITIVE HEAD OFFSET",
    0x1703: "RECOVERED DATA WITH NEGATIVE HEAD OFFSET",
    0x1704: "RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED",
    0x1705: "RECOVERED DATA USING PREVIOUS SECTOR ID",
    0x1706: "RECOVERED DATA WITHOUT ECC - DATA AUTO-REALLOCATED",
    0x1707: "RECOVERED DATA WITHOUT ECC - RECOMMEND REASSIGNMENT",
    0x1708: "RECOVERED DATA WITHOUT ECC - RECOMMEND REWRITE",
    0x1709: "RECOVERED DATA WITHOUT ECC - DATA REWRITTEN",
    0x1800: "RECOVERED DATA WITH ERROR CORRECTION APPLIED",
    0x1801: "RECOVERED DATA WITH ERROR CORR. & RETRIES APPLIED",
    0x1802: "RECOVERED DATA - DATA AUTO-REALLOCATED",
    0x1803: "RECOVERED DATA WITH CIRC",
    0x1804: "RECOVERED DATA WITH L-EC",
    0x1805: "RECOVERED DATA - RECOMMEND REASSIGNMENT",
    0x1806: "RECOVERED DATA - RECOMMEND REWRITE",
    0x1807: "RECOVERED DATA WITH ECC - DATA REWRITTEN",
    0x1808: "RECOVERED DATA WITH LINKING",
    0x1900: "DEFECT LIST ERROR",
    0x1901: "DEFECT LIST NOT AVAILABLE",
    0x1902: "DEFECT LIST ERROR IN PRIMARY LIST",
    0x1903: "DEFECT LIST ERROR IN GROWN LIST",
    0x1A00: "PARAMETER LIST LENGTH ERROR",
    0x1B00: "SYNCHRONOUS DATA TRANSFER ERROR",
    0x1C00: "DEFECT LIST NOT FOUND",
    0x1C01: "PRIMARY DEFECT LIST NOT FOUND",
    0x1C02: "GROWN DEFECT LIST NOT FOUND",
    0x1D00: "MISCOMPARE DURING VERIFY OPERATION",
    0x1D01: "MISCOMPARE VERIFY OF UNMAPPED LBA",
    0x1E00: "RECOVERED ID WITH ECC CORRECTION",
    0x1F00: "PARTIAL DEFECT LIST TRANSFER",
    0x2000: "INVALID COMMAND OPERATION CODE",
    0x2001: "ACCESS DENIED - INITIATOR PENDING-ENROLLED",
    0x2002: "ACCESS DENIED - NO ACCESS RIGHTS",
    0x2003: "ACCESS DENIED - INVALID MGMT ID KEY",
    0x2004: "ILLEGAL COMMAND WHILE IN WRITE CAPABLE STATE",
    0x2005: "Obsolete",
    0x2006: "ILLEGAL COMMAND WHILE IN EXPLICIT ADDRESS MODE",
    0x2007: "ILLEGAL COMMAND WHILE IN IMPLICIT ADDRESS MODE",
    0x2008: "ACCESS DENIED - ENROLLMENT CONFLICT",
    0x2009: "ACCESS DENIED - INVALID LU IDENTIFIER",
    0x200A: "ACCESS DENIED - INVALID PROXY TOKEN",
    0x200B: "ACCESS DENIED - ACL LUN CONFLICT",
    0x200C: "ILLEGAL COMMAND WHEN NOT IN APPEND-ONLY MODE",
    0x2100: "LOGICAL BLOCK ADDRESS OUT OF RANGE",
    0x2101: "INVALID ELEMENT ADDRESS",
    0x2102: "INVALID ADDRESS FOR WRITE",
    0x2103: "INVALID WRITE CROSSING LAYER JUMP",
    0x2104: "UNALIGNED WRITE COMMAND",
    0x2105: "WRITE BOUNDARY VIOLATION",
    0x2106: "ATTEMPT TO READ INVALID DATA",
    0x2107: "READ BOUNDARY VIOLATION",
    0x2200: "ILLEGAL FUNCTION (USE 20 00, 24 00, OR 26 00)",
    0x2300: "INVALID TOKEN OPERATION, CAUSE NOT REPORTABLE",
    0x2301: "INVALID TOKEN OPERATION, UNSUPPORTED TOKEN TYPE",
    0x2302: "INVALID TOKEN OPERATION, REMOTE TOKEN USAGE NOT SUPPORTED",
    0x2303: "INVALID TOKEN OPERATION, REMOTE ROD TOKEN CREATION NOT SUPPORTED",
    0x2304: "INVALID TOKEN OPERATION, TOKEN UNKNOWN",
    0x2305: "INVALID TOKEN OPERATION, TOKEN CORRUPT",
    0x2306: "INVALID TOKEN OPERATION, TOKEN REVOKED",
    0x2307: "INVALID TOKEN OPERATION, TOKEN EXPIRED",
    0x2308: "INVALID TOKEN OPERATION, TOKEN CANCELLED",
    0x2309: "INVALID TOKEN OPERATION, TOKEN DELETED",
    0x230A: "INVALID TOKEN OPERATION, INVALID TOKEN LENGTH",
    0x2400: "Invalid Field In CDB",
    0x2401: "CDB Decryption Error",
    0x2404: "Security Audit Value Frozen",
    0x2405: "Security Working Key Frozen",
    0x2406: "Nonce Not Unique",
    0x2407: "Nonce Timestamp Out Of Range",
    0x2408: "Invalid XCDB",
    0x2500: "LOGICAL UNIT NOT SUPPORTED",
    0x2600: "INVALID FIELD IN PARAMETER LIST",
    0x2601: "PARAMETER NOT SUPPORTED",
    0x2602: "PARAMETER VALUE INVALID",
    0x2603: "THRESHOLD PARAMETERS NOT SUPPORTED",
    0x2604: "INVALID RELEASE OF PERSISTENT RESERVATION",
    0x2605: "DATA DECRYPTION ERROR",
    0x2606: "TOO MANY TARGET DESCRIPTORS",
    0x2607: "UNSUPPORTED TARGET DESCRIPTOR TYPE CODE",
    0x2608: "TOO MANY SEGMENT DESCRIPTORS",
    0x2609: "UNSUPPORTED SEGMENT DESCRIPTOR TYPE CODE",
    0x260A: "UNEXPECTED INEXACT SEGMENT",
    0x260B: "INLINE DATA LENGTH EXCEEDED",
    0x260C: "INVALID OPERATION FOR COPY SOURCE OR DESTINATION",
    0x260D: "COPY SEGMENT GRANULARITY VIOLATION",
    0x260E: "INVALID PARAMETER WHILE PORT IS ENABLED",
    0x260F: "INVALID DATA-OUT BUFFER INTEGRITY CHECK VALUE",
    0x2610: "DATA DECRYPTION KEY FAIL LIMIT REACHED",
    0x2611: "INCOMPLETE KEY-ASSOCIATED DATA SET",
    0x2612: "VENDOR SPECIFIC KEY REFERENCE NOT FOUND",
    0x2700: "WRITE PROTECTED",
    0x2701: "HARDWARE WRITE PROTECTED",
    0x2702: "LOGICAL UNIT SOFTWARE WRITE PROTECTED",
    0x2703: "ASSOCIATED WRITE PROTECT",
    0x2704: "PERSISTENT WRITE PROTECT",
    0x2705: "PERMANENT WRITE PROTECT",
    0x2706: "CONDITIONAL WRITE PROTECT",
    0x2707: "SPACE ALLOCATION FAILED WRITE PROTECT",
    0x2708: "ZONE IS READ ONLY",
    0x2800: "NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED",
    0x2801: "IMPORT OR EXPORT ELEMENT ACCESSED",
    0x2802: "FORMAT-LAYER MAY HAVE CHANGED",
    0x2803: "IMPORT/EXPORT ELEMENT ACCESSED, MEDIUM CHANGED",
    0x2900: "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED",
    0x2901: "POWER ON OCCURRED",
    0x2902: "SCSI BUS RESET OCCURRED",
    0x2903: "BUS DEVICE RESET FUNCTION OCCURRED",
    0x2904: "DEVICE INTERNAL RESET",
    0x2905: "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED",
    0x2906: "TRANSCEIVER MODE CHANGED TO LVD",
    0x2907: "I_T NEXUS LOSS OCCURRED",
    0x2A00: "PARAMETERS CHANGED",
    0x2A01: "MODE PARAMETERS CHANGED",
    0x2A02: "LOG PARAMETERS CHANGED",
    0x2A03: "RESERVATIONS PREEMPTED",
    0x2A04: "RESERVATIONS RELEASED",
    0x2A05: "REGISTRATIONS PREEMPTED",
    0x2A06: "ASYMMETRIC ACCESS STATE CHANGED",
    0x2A07: "IMPLICIT ASYMMETRIC ACCESS STATE TRANSITION FAILED",
    0x2A08: "PRIORITY CHANGED",
    0x2A09: "CAPACITY DATA HAS CHANGED",
    0x2A0A: "ERROR HISTORY I_T NEXUS CLEARED",
    0x2A0B: "ERROR HISTORY SNAPSHOT RELEASED",
    0x2A0C: "ERROR RECOVERY ATTRIBUTES HAVE CHANGED",
    0x2A0D: "DATA ENCRYPTION CAPABILITIES CHANGED",
    0x2A10: "TIMESTAMP CHANGED",
    0x2A11: "DATA ENCRYPTION PARAMETERS CHANGED BY ANOTHER I_T NEXUS",
    0x2A12: "DATA ENCRYPTION PARAMETERS CHANGED BY VENDOR SPECIFIC EVENT",
    0x2A13: "DATA ENCRYPTION KEY INSTANCE COUNTER HAS CHANGED",
    0x2A14: "SA CREATION CAPABILITIES DATA HAS CHANGED",
    0x2A15: "MEDIUM REMOVAL PREVENTION PREEMPTED",
    0x2B00: "COPY CANNOT EXECUTE SINCE HOST CANNOT DISCONNECT",
    0x2C00: "COMMAND SEQUENCE ERROR",
    0x2C01: "TOO MANY WINDOWS SPECIFIED",
    0x2C02: "INVALID COMBINATION OF WINDOWS SPECIFIED",
    0x2C03: "CURRENT PROGRAM AREA IS NOT EMPTY",
    0x2C04: "CURRENT PROGRAM AREA IS EMPTY",
    0x2C05: "ILLEGAL POWER CONDITION REQUEST",
    0x2C06: "PERSISTENT PREVENT CONFLICT",
    0x2C07: "PREVIOUS BUSY STATUS",
    0x2C08: "PREVIOUS TASK SET FULL STATUS",
    0x2C09: "PREVIOUS RESERVATION CONFLICT STATUS",
    0x2C0A: "PARTITION OR COLLECTION CONTAINS USER OBJECTS",
    0x2C0B: "NOT RESERVED",
    0x2C0C: "ORWRITE GENERATION DOES NOT MATCH",
    0x2C0D: "RESET WRITE POINTER NOT ALLOWED",
    0x2C0E: "ZONE IS OFFLINE",
    0x2D00: "OVERWRITE ERROR ON UPDATE IN PLACE",
    0x2E00: "INSUFFICIENT TIME FOR OPERATION",
    0x2E01: "COMMAND TIMEOUT BEFORE PROCESSING",
    0x2E02: "COMMAND TIMEOUT DURING PROCESSING",
    0x2E03: "COMMAND TIMEOUT DURING PROCESSING DUE TO ERROR RECOVERY",
    0x2F00: "COMMANDS CLEARED BY ANOTHER INITIATOR",
    0x2F01: "COMMANDS CLEARED BY POWER LOSS NOTIFICATION",
    0x2F02: "COMMANDS CLEARED BY DEVICE SERVER",
    0x2F03: "SOME COMMANDS CLEARED BY QUEUING LAYER EVENT",
    0x3000: "INCOMPATIBLE MEDIUM INSTALLED",
    0x3001: "CANNOT READ MEDIUM - UNKNOWN FORMAT",
    0x3002: "CANNOT READ MEDIUM - INCOMPATIBLE FORMAT",
    0x3003: "CLEANING CARTRIDGE INSTALLED",
    0x3004: "CANNOT WRITE MEDIUM - UNKNOWN FORMAT",
    0x3005: "CANNOT WRITE MEDIUM - INCOMPATIBLE FORMAT",
    0x3006: "CANNOT FORMAT MEDIUM - INCOMPATIBLE MEDIUM",
    0x3007: "CLEANING FAILURE",
    0x3008: "CANNOT WRITE - APPLICATION CODE MISMATCH",
    0x3009: "CURRENT SESSION NOT FIXATED FOR APPEND",
    0x300A: "CLEANING REQUEST REJECTED",
    0x300C: "WORM MEDIUM - OVERWRITE ATTEMPTED",
    0x300D: "WORM MEDIUM - INTEGRITY CHECK",
    0x3010: "MEDIUM NOT FORMATTED",
    0x3011: "INCOMPATIBLE VOLUME TYPE",
    0x3012: "INCOMPATIBLE VOLUME QUALIFIER",
    0x3013: "CLEANING VOLUME EXPIRED",
    0x3100: "MEDIUM FORMAT CORRUPTED",
    0x3101: "FORMAT COMMAND FAILED",
    0x3102: "ZONED FORMATTING FAILED DUE TO SPARE LINKING",
    0x3103: "SANITIZE COMMAND FAILED",
    0x3200: "NO DEFECT SPARE LOCATION AVAILABLE",
    0x3201: "DEFECT LIST UPDATE FAILURE",
    0x3300: "TAPE LENGTH ERROR",
    0x3400: "ENCLOSURE FAILURE",
    0x3500: "ENCLOSURE SERVICES FAILURE",
    0x3501: "UNSUPPORTED ENCLOSURE FUNCTION",
    0x3502: "ENCLOSURE SERVICES UNAVAILABLE",
    0x3503: "ENCLOSURE SERVICES TRANSFER FAILURE",
    0x3504: "ENCLOSURE SERVICES TRANSFER REFUSED",
    0x3505: "ENCLOSURE SERVICES CHECKSUM ERROR",
    0x3600: "RIBBON, INK, OR TONER FAILURE",
    0x3700: "ROUNDED PARAMETER",
    0x3800: "EVENT STATUS NOTIFICATION",
    0x3802: "ESN - POWER MANAGEMENT CLASS EVENT",
    0x3804: "ESN - MEDIA CLASS EVENT",
    0x3806: "ESN - DEVICE BUSY CLASS EVENT",
    0x3807: "THIN PROVISIONING SOFT THRESHOLD REACHED",
    0x3900: "SAVING PARAMETERS NOT SUPPORTED",
    0x3A00: "MEDIUM NOT PRESENT",
    0x3A01: "MEDIUM NOT PRESENT - TRAY CLOSED",
    0x3A02: "MEDIUM NOT PRESENT - TRAY OPEN",
    0x3A03: "MEDIUM NOT PRESENT - LOADABLE",
    0x3A04: "MEDIUM NOT PRESENT - MEDIUM AUXILIARY MEMORY ACCESSIBLE",
    0x3B00: "SEQUENTIAL POSITIONING ERROR",
    0x3B01: "TAPE POSITION ERROR AT BEGINNING-OF-MEDIUM",
    0x3B02: "TAPE POSITION ERROR AT END-OF-MEDIUM",
    0x3B03: "TAPE OR ELECTRONIC VERTICAL FORMS UNIT NOT READY",
    0x3B04: "SLEW FAILURE",
    0x3B05: "PAPER JAM",
    0x3B06: "FAILED TO SENSE TOP-OF-FORM",
    0x3B07: "FAILED TO SENSE BOTTOM-OF-FORM",
    0x3B08: "REPOSITION ERROR",
    0x3B09: " READ PAST END OF MEDIUM",
    0x3B0A: " READ PAST BEGINNING OF MEDIUM",
    0x3B0B: " POSITION PAST END OF MEDIUM",
    0x3B0C: "POSITION PAST BEGINNING OF MEDIUM",
    0x3B0D: "MEDIUM DESTINATION ELEMENT FULL",
    0x3B0E: "MEDIUM SOURCE ELEMENT EMPTY",
    0x3B0F: "END OF MEDIUM REACHED",
    0x3B11: "MEDIUM MAGAZINE NOT ACCESSIBLE",
    0x3B12: "MEDIUM MAGAZINE REMOVED",
    0x3B13: "MEDIUM MAGAZINE INSERTED",
    0x3B14: "MEDIUM MAGAZINE LOCKED",
    0x3B15: "MEDIUM MAGAZINE UNLOCKED",
    0x3B16: "MECHANICAL POSITIONING OR CHANGER ERROR",
    0x3B17: "READ PAST END OF USER OBJECT",
    0x3B18: "ELEMENT DISABLED",
    0x3B19: "ELEMENT ENABLED",
    0x3B1A: "DATA TRANSFER DEVICE REMOVED",
    0x3B1B: "DATA TRANSFER DEVICE INSERTED",
    0x3B1C: "TOO MANY LOGICAL OBJECTS ON PARTITION TO SUPPORT OPERATION",
    0x3D00: "INVALID BITS IN IDENTIFY MESSAGE",
    0x3E00: "LOGICAL UNIT HAS NOT SELF-CONFIGURED YET",
    0x3E01: "LOGICAL UNIT FAILURE",
    0x3E02: "TIMEOUT ON LOGICAL UNIT",
    0x3E03: "LOGICAL UNIT FAILED SELF-TEST",
    0x3E04: "LOGICAL UNIT UNABLE TO UPDATE SELF-TEST LOG",
    0x3F00: "TARGET OPERATING CONDITIONS HAVE CHANGED",
    0x3F01: "MICROCODE HAS BEEN CHANGED",
    0x3F02: "CHANGED OPERATING DEFINITION",
    0x3F03: "INQUIRY DATA HAS CHANGED",
    0x3F04: "COMPONENT DEVICE ATTACHED",
    0x3F05: "DEVICE IDENTIFIER CHANGED",
    0x3F06: "REDUNDANCY GROUP CREATED OR MODIFIED",
    0x3F07: "REDUNDANCY GROUP DELETED",
    0x3F08: "SPARE CREATED OR MODIFIED",
    0x3F09: "SPARE DELETED",
    0x3F0A: "VOLUME SET CREATED OR MODIFIED",
    0x3F0B: "VOLUME SET DELETED",
    0x3F0C: "VOLUME SET DEASSIGNED",
    0x3F0D: "VOLUME SET REASSIGNED",
    0x3F0E: "REPORTED LUNS DATA HAS CHANGED",
    0x3F0F: "ECHO BUFFER OVERWRITTEN",
    0x3F10: "MEDIUM LOADABLE",
    0x3F11: "MEDIUM AUXILIARY MEMORY ACCESSIBLE",
    0x3F12: "iSCSI IP ADDRESS ADDED",
    0x3F13: "iSCSI IP ADDRESS REMOVED",
    0x3F14: "iSCSI IP ADDRESS CHANGED",
    0x3F15: "INSPECT REFERRALS SENSE DESCRIPTORS",
    0x3F16: "MICROCODE HAS BEEN CHANGED WITHOUT RESET",
    0x4000: "RAM FAILURE (SHOULD USE 40 NN)",
    0x4100: "DATA PATH FAILURE (SHOULD USE 40 NN)",
    0x4200: "POWER-ON OR SELF-TEST FAILURE (SHOULD USE 40 NN)",
    0x4300: "MESSAGE ERROR",
    0x4400: "INTERNAL TARGET FAILURE",
    0x4401: "PERSISTENT RESERVATION INFORMATION LOST",
    0x4471: "ATA DEVICE FAILED SET FEATURES",
    0x4500: "SELECT OR RESELECT FAILURE",
    0x4600: "UNSUCCESSFUL SOFT RESET",
    0x4700: "SCSI PARITY ERROR",
    0x4701: "DATA PHASE CRC ERROR DETECTED",
    0x4702: "SCSI PARITY ERROR DETECTED DURING ST DATA PHASE",
    0x4703: "INFORMATION UNIT iuCRC ERROR DETECTED",
    0x4704: "ASYNCHRONOUS INFORMATION PROTECTION ERROR DETECTED",
    0x4705: "PROTOCOL SERVICE CRC ERROR",
    0x4706: "PHY TEST FUNCTION IN PROGRESS",
    0x477F: "SOME COMMANDS CLEARED BY ISCSI PROTOCOL EVENT",
    0x4800: "INITIATOR DETECTED ERROR MESSAGE RECEIVED",
    0x4900: "INVALID MESSAGE ERROR",
    0x4A00: "COMMAND PHASE ERROR",
    0x4B00: "DATA PHASE ERROR",
    0x4B01: "INVALID TARGET PORT TRANSFER TAG RECEIVED",
    0x4B02: "TOO MUCH WRITE DATA",
    0x4B03: "ACK/NAK TIMEOUT",
    0x4B04: "NAK RECEIVED",
    0x4B05: "DATA OFFSET ERROR",
    0x4B06: "INITIATOR RESPONSE TIMEOUT",
    0x4B07: "CONNECTION LOST",
    0x4B08: "DATA-IN BUFFER OVERFLOW - DATA BUFFER SIZE",
    0x4B09: "DATA-IN BUFFER OVERFLOW - DATA BUFFER DESCRIPTOR AREA",
    0x4B0A: "DATA-IN BUFFER ERROR",
    0x4B0B: "DATA-OUT BUFFER OVERFLOW - DATA BUFFER SIZE",
    0x4B0C: "DATA-OUT BUFFER OVERFLOW - DATA BUFFER DESCRIPTOR AREA",
    0x4B0D: "DATA-OUT BUFFER ERROR",
    0x4B0E: "PCIE FABRIC ERROR",
    0x4B0F: "PCIE COMPLETION TIMEOUT",
    0x4B10: "PCIE COMPLETER ABORT",
    0x4B11: "PCIE POISONED TLP RECEIVED",
    0x4B12: "PCIE ECRC CHECK FAILED",
    0x4B13: "PCIE UNSUPPORTED REQUEST",
    0x4B14: "PCIE ACS VIOLATION",
    0x4B15: "PCIE TLP PREFIX BLOCKED",
    0x4C00: "LOGICAL UNIT FAILED SELF-CONFIGURATION",
    0x4E00: "OVERLAPPED COMMANDS ATTEMPTED",
    0x5000: "WRITE APPEND ERROR",
    0x5001: "WRITE APPEND POSITION ERROR",
    0x5002: "POSITION ERROR RELATED TO TIMING",
    0x5100: "ERASE FAILURE",
    0x5101: "ERASE FAILURE - INCOMPLETE ERASE OPERATION DETECTED",
    0x5200: "CARTRIDGE FAULT",
    0x5300: "MEDIA LOAD OR EJECT FAILED",
    0x5301: "UNLOAD TAPE FAILURE",
    0x5302: "MEDIUM REMOVAL PREVENTED",
    0x5303: "MEDIUM REMOVAL PREVENTED BY DATA TRANSFER ELEMENT",
    0x5304: "MEDIUM THREAD OR UNTHREAD FAILURE",
    0x5305: "VOLUME IDENTIFIER INVALID",
    0x5306: "VOLUME IDENTIFIER MISSING",
    0x5307: "DUPLICATE VOLUME IDENTIFIER",
    0x5308: "ELEMENT STATUS UNKNOWN",
    0x5309: "DATA TRANSFER DEVICE ERROR - LOAD FAILED",
    0x530A: "DATA TRANSFER DEVICE ERROR - UNLOAD FAILED",
    0x530B: "DATA TRANSFER DEVICE ERROR - UNLOAD MISSING",
    0x530C: "DATA TRANSFER DEVICE ERROR - EJECT FAILED",
    0x530D: "DATA TRANSFER DEVICE ERROR - LIBRARY COMMUNICATION FAILED",
    0x5400: "SCSI TO HOST SYSTEM INTERFACE FAILURE",
    0x5500: "SYSTEM RESOURCE FAILURE",
    0x5501: "SYSTEM BUFFER FULL",
    0x5502: "INSUFFICIENT RESERVATION RESOURCES",
    0x5503: "INSUFFICIENT RESOURCES",
    0x5504: "INSUFFICIENT REGISTRATION RESOURCES",
    0x5505: "INSUFFICIENT ACCESS CONTROL RESOURCES",
    0x5506: "AUXILIARY MEMORY OUT OF SPACE",
    0x5507: "QUOTA ERROR",
    0x5508: "MAXIMUM NUMBER OF SUPPLEMENTAL DECRYPTION KEYS EXCEEDED",
    0x5509: "MEDIUM AUXILIARY MEMORY NOT ACCESSIBLE",
    0x550A: "DATA CURRENTLY UNAVAILABLE",
    0x550B: "INSUFFICIENT POWER FOR OPERATION",
    0x550C: "INSUFFICIENT RESOURCES TO CREATE ROD",
    0x550D: "INSUFFICIENT RESOURCES TO CREATE ROD TOKEN",
    0x550E: "INSUFFICIENT ZONE RESOURCES",
    0x5700: "UNABLE TO RECOVER TABLE-OF-CONTENTS",
    0x5800: "GENERATION DOES NOT EXIST",
    0x5900: "UPDATED BLOCK READ",
    0x5A00: "OPERATOR REQUEST OR STATE CHANGE INPUT",
    0x5A01: "OPERATOR MEDIUM REMOVAL REQUEST",
    0x5A02: "OPERATOR SELECTED WRITE PROTECT",
    0x5A03: "OPERATOR SELECTED WRITE PERMIT",
    0x5B00: "LOG EXCEPTION",
    0x5B01: "THRESHOLD CONDITION MET",
    0x5B02: "LOG COUNTER AT MAXIMUM",
    0x5B03: "LOG LIST CODES EXHAUSTED",
    0x5C00: "RPL STATUS CHANGE",
    0x5C01: "SPINDLES SYNCHRONIZED",
    0x5C02: "SPINDLES NOT SYNCHRONIZED",
    0x5D00: "FAILURE PREDICTION THRESHOLD EXCEEDED",
    0x5D01: "MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED",
    0x5D02: "LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED",
    0x5D03: "SPARE AREA EXHAUSTION PREDICTION THRESHOLD EXCEEDED",
    0x5D10: "HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
    0x5D11: "HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
    0x5D12: "HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
    0x5D13: "HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
    0x5D14: "HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
    0x5D15: "HARDWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
    0x5D16: "HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
    0x5D17: "HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
    0x5D18: "HARDWARE IMPENDING FAILURE CONTROLLER DETECTED",
    0x5D19: "HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
    0x5D1A: "HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
    0x5D1B: "HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
    0x5D1C: "HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
    0x5D20: "CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
    0x5D21: "CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
    0x5D22: "CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
    0x5D23: "CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
    0x5D24: "CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
    0x5D25: "CONTROLLER IMPENDING FAILURE ACCESS TIMES TOO HIGH",
    0x5D26: "CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH",
    0x5D27: "CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS",
    0x5D28: "CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED",
    0x5D29: "CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE",
    0x5D2A: "CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE",
    0x5D2B: "CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT",
    0x5D2C: "CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
    0x5D30: "DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
    0x5D31: "DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
    0x5D32: "DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
    0x5D33: "DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
    0x5D34: "DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
    0x5D35: "DATA CHANNEL IMPENDING FAILURE ACCESS TIMES TOO HIGH",
    0x5D36: "DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH",
    0x5D37: "DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS",
    0x5D38: "DATA CHANNEL IMPENDING FAILURE CONTROLLER DETECTED",
    0x5D39: "DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE",
    0x5D3A: "DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE",
    0x5D3B: "DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT",
    0x5D3C: "DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
    0x5D40: "SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
    0x5D41: "SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
    0x5D42: "SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
    0x5D43: "SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
    0x5D44: "SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
    0x5D45: "SERVO IMPENDING FAILURE ACCESS TIMES TOO HIGH",
    0x5D46: "SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH",
    0x5D47: "SERVO IMPENDING FAILURE CHANNEL PARAMETRICS",
    0x5D48: "SERVO IMPENDING FAILURE CONTROLLER DETECTED",
    0x5D49: "SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE",
    0x5D4A: "SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE",
    0x5D4B: "SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT",
    0x5D4C: "SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
    0x5D50: "SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
    0x5D51: "SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
    0x5D52: "SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
    0x5D53: "SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
    0x5D54: "SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
    0x5D55: "SPINDLE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
    0x5D56: "SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
    0x5D57: "SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS",
    0x5D58: "SPINDLE IMPENDING FAILURE CONTROLLER DETECTED",
    0x5D59: "SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
    0x5D5A: "SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE",
    0x5D5B: "SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT",
    0x5D5C: "SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
    0x5D60: "FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
    0x5D61: "FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
    0x5D62: "FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
    0x5D63: "FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
    0x5D64: "FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
    0x5D65: "FIRMWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
    0x5D66: "FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
    0x5D67: "FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
    0x5D68: "FIRMWARE IMPENDING FAILURE CONTROLLER DETECTED",
    0x5D69: "FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
    0x5D6A: "FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
    0x5D6B: "FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
    0x5D6C: "FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
    0x5DFF: "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)",
    0x5E00: "LOW POWER CONDITION ON",
    0x5E01: "IDLE CONDITION ACTIVATED BY TIMER",
    0x5E02: "STANDBY CONDITION ACTIVATED BY TIMER",
    0x5E03: "IDLE CONDITION ACTIVATED BY COMMAND",
    0x5E04: "STANDBY CONDITION ACTIVATED BY COMMAND",
    0x5E05: "IDLE_B CONDITION ACTIVATED BY TIMER",
    0x5E06: "IDLE_B CONDITION ACTIVATED BY COMMAND",
    0x5E07: "IDLE_C CONDITION ACTIVATED BY TIMER",
    0x5E08: "IDLE_C CONDITION ACTIVATED BY COMMAND",
    0x5E09: "STANDBY_Y CONDITION ACTIVATED BY TIMER",
    0x5E0A: "STANDBY_Y CONDITION ACTIVATED BY COMMAND",
    0x5E41: "POWER STATE CHANGE TO ACTIVE",
    0x5E42: "POWER STATE CHANGE TO IDLE",
    0x5E43: "POWER STATE CHANGE TO STANDBY",
    0x5E45: "POWER STATE CHANGE TO SLEEP",
    0x5E47: "POWER STATE CHANGE TO DEVICE CONTROL",
    0x6000: "LAMP FAILURE",
    0x6100: "VIDEO ACQUISITION ERROR",
    0x6101: "UNABLE TO ACQUIRE VIDEO",
    0x6102: "OUT OF FOCUS",
    0x6200: "SCAN HEAD POSITIONING ERROR",
    0x6300: "END OF USER AREA ENCOUNTERED ON THIS TRACK",
    0x6301: "PACKET DOES NOT FIT IN AVAILABLE SPACE",
    0x6400: "ILLEGAL MODE FOR THIS TRACK",
    0x6401: "INVALID PACKET SIZE",
    0x6500: "VOLTAGE FAULT",
    0x6600: "AUTOMATIC DOCUMENT FEEDER COVER UP",
    0x6601: "AUTOMATIC DOCUMENT FEEDER LIFT UP",
    0x6602: "DOCUMENT JAM IN AUTOMATIC DOCUMENT FEEDER",
    0x6603: "DOCUMENT MISS FEED AUTOMATIC IN DOCUMENT FEEDER",
    0x6700: "CONFIGURATION FAILURE",
    0x6701: "CONFIGURATION OF INCAPABLE LOGICAL UNITS FAILED",
    0x6702: "ADD LOGICAL UNIT FAILED",
    0x6703: "MODIFICATION OF LOGICAL UNIT FAILED",
    0x6704: "EXCHANGE OF LOGICAL UNIT FAILED",
    0x6705: "REMOVE OF LOGICAL UNIT FAILED",
    0x6706: "ATTACHMENT OF LOGICAL UNIT FAILED",
    0x6707: "CREATION OF LOGICAL UNIT FAILED",
    0x6708: "ASSIGN FAILURE OCCURRED",
    0x6709: "MULTIPLY ASSIGNED LOGICAL UNIT",
    0x670A: "SET TARGET PORT GROUPS COMMAND FAILED",
    0x670B: "ATA DEVICE FEATURE NOT ENABLED",
    0x6800: "LOGICAL UNIT NOT CONFIGURED",
    0x6801: "SUBSIDIARY LOGICAL UNIT NOT CONFIGURED",
    0x6900: "DATA LOSS ON LOGICAL UNIT",
    0x6901: "MULTIPLE LOGICAL UNIT FAILURES",
    0x6902: "PARITY/DATA MISMATCH",
    0x6A00: "INFORMATIONAL, REFER TO LOG",
    0x6B00: "STATE CHANGE HAS OCCURRED",
    0x6B01: "REDUNDANCY LEVEL GOT BETTER",
    0x6B02: "REDUNDANCY LEVEL GOT WORSE",
    0x6C00: "REBUILD FAILURE OCCURRED",
    0x6D00: "RECALCULATE FAILURE OCCURRED",
    0x6E00: "COMMAND TO LOGICAL UNIT FAILED",
    0x6F00: "COPY PROTECTION KEY EXCHANGE FAILURE - AUTHENTICATION FAILURE",
    0x6F01: "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT PRESENT",
    0x6F02: "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED",
    0x6F03: "READ OF SCRAMBLED SECTOR WITHOUT AUTHENTICATION",
    0x6F04: "MEDIA REGION CODE IS MISMATCHED TO LOGICAL UNIT REGION",
    0x6F05: "DRIVE REGION MUST BE PERMANENT/REGION RESET COUNT ERROR",
    0x6F06: "INSUFFICIENT BLOCK COUNT FOR BINDING NONCE RECORDING",
    0x6F07: "CONFLICT IN BINDING NONCE RECORDING",
    0x7100: "DECOMPRESSION EXCEPTION LONG ALGORITHM ID",
    0x7200: "SESSION FIXATION ERROR",
    0x7201: "SESSION FIXATION ERROR WRITING LEAD-IN",
    0x7202: "SESSION FIXATION ERROR WRITING LEAD-OUT",
    0x7203: "SESSION FIXATION ERROR - INCOMPLETE TRACK IN SESSION",
    0x7204: "EMPTY OR PARTIALLY WRITTEN RESERVED TRACK",
    0x7205: "NO MORE TRACK RESERVATIONS ALLOWED",
    0x7206: "RMZ EXTENSION IS NOT ALLOWED",
    0x7207: "NO MORE TEST ZONE EXTENSIONS ARE ALLOWED",
    0x7300: "CD CONTROL ERROR",
    0x7301: "POWER CALIBRATION AREA ALMOST FULL",
    0x7302: "POWER CALIBRATION AREA IS FULL",
    0x7303: "POWER CALIBRATION AREA ERROR",
    0x7304: "PROGRAM MEMORY AREA UPDATE FAILURE",
    0x7305: "PROGRAM MEMORY AREA IS FULL",
    0x7306: "RMA/PMA IS ALMOST FULL",
    0x7310: "CURRENT POWER CALIBRATION AREA ALMOST FULL",
    0x7311: "CURRENT POWER CALIBRATION AREA IS FULL",
    0x7317: "RDZ IS FULL",
    0x7400: "SECURITY ERROR",
    0x7401: "UNABLE TO DECRYPT DATA",
    0x7402: "UNENCRYPTED DATA ENCOUNTERED WHILE DECRYPTING",
    0x7403: "INCORRECT DATA ENCRYPTION KEY",
    0x7404: "CRYPTOGRAPHIC INTEGRITY VALIDATION FAILED",
    0x7405: "ERROR DECRYPTING DATA",
    0x7406: "UNKNOWN SIGNATURE VERIFICATION KEY",
    0x7407: "ENCRYPTION PARAMETERS NOT USEABLE",
    0x7408: "DIGITAL SIGNATURE VALIDATION FAILURE",
    0x7409: "ENCRYPTION MODE MISMATCH ON READ",
    0x740A: "ENCRYPTED BLOCK NOT RAW READ ENABLED",
    0x740B: "INCORRECT ENCRYPTION PARAMETERS",
    0x740C: "UNABLE TO DECRYPT PARAMETER LIST",
    0x740D: "ENCRYPTION ALGORITHM DISABLED",
    0x7410: "SA CREATION PARAMETER VALUE INVALID",
    0x7411: "SA CREATION PARAMETER VALUE REJECTED",
    0x7412: "INVALID SA USAGE",
    0x7421: "DATA ENCRYPTION CONFIGURATION PREVENTED",
    0x7430: "SA CREATION PARAMETER NOT SUPPORTED",
    0x7440: "AUTHENTICATION FAILED",
    0x7461: "EXTERNAL DATA ENCRYPTION KEY MANAGER ACCESS ERROR",
    0x7462: "EXTERNAL DATA ENCRYPTION KEY MANAGER ERROR",
    0x7463: "EXTERNAL DATA ENCRYPTION KEY NOT FOUND",
    0x7464: "EXTERNAL DATA ENCRYPTION REQUEST NOT AUTHORIZED",
    0x746E: "EXTERNAL DATA ENCRYPTION CONTROL TIMEOUT",
    0x746F: "EXTERNAL DATA ENCRYPTION CONTROL ERROR",
    0x7471: "LOGICAL UNIT ACCESS NOT AUTHORIZED",
    0x7479: "SECURITY CONFLICT IN TRANSLATED DEVICE",
}


# Exception Class for a SCSI REQUEST SENSE command
class SCSICheckCondition(Exception):
    """Exception raised for errors in the SCSIDevice execute method

    Attributes:
        sense -- byte array with additional data
    """

    # sense data descriptor
    _sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
    }

    # information sense data descriptor
    _info_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "valid": [0x80, 2],
        "information": [0xFFFFFFFFFFFFFFFF, 4],
    }

    # command-specific information sense data descriptor
    _cmd_info_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "cmd_specific_information": [0xFFFFFFFFFFFFFFFF, 4],
    }

    # sense key specific sense data descriptor
    _skey_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "sksv": [0x80, 4],
        "skey_specific_information": [0x7FFFFF, 4],
    }

    # field pointer sense key specific information
    _fptr_skey_sdata_desc_bits = {
        "sksv": [0x80, 0],
        "cd": [0x40, 0],
        "bpv": [0x08, 0],
        "bit_pointer": [0x07, 0],
        "field_pointer": [0xFFFF, 1],
    }

    # actual retry count sense key specific information
    _retry_count_skey_sdata_desc_bits = {
        "sksv": [0x80, 0],
        "actual_retry_counter": [0xFFFF, 1],
    }

    # progress indication sense key specific information
    _progress_skey_sdata_desc_bits = {
        "sksv": [0x80, 0],
        "progress_indication": [0xFFFF, 1],
    }

    # segment pointer sense key specific information
    _segptr_skey_sdata_desc_bits = {
        "sksv": [0x80, 0],
        "sd": [0x40, 0],
        "bpv": [0x20, 0],
        "bit_pointer": [0x07, 0],
        "field_pointer": [0xFFFF, 1],
    }

    # unit attention condition queue overflow sense key specific info
    _uacqo_skey_sdata_desc_bits = {
        "sksv": [0x80, 0],
        "overflow": [0x01, 0],
    }

    # field replaceable unit sense data descriptor
    _fld_replace_unit_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "field_replaceable_unit_code": [0xFF, 3],
    }

    # stream commands sense data descriptor
    _stream_cmd_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "filemark": [0x80, 3],
        "eom": [0x40, 3],
        "ili": [0x20, 3],
    }

    # block commands sense data descriptor
    _blk_cmd_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "ili": [0x20, 3],
    }

    # OSD object identification sense data descriptor
    _osd_obj_ident_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "not_initiated_command_function": [0xFFFFFF, 8],
        "completed_command_functions": [0xFFFFFFFF, 12],
        "partition_id": [0xFFFFFFFFFFFFFF, 16],
        "object_id": [0xFFFFFFFFFFFFFF, 24],
    }

    # bits contained in the not_initiated_command_function field
    _osd_cmd_func_bits = {
        "validation": [0x80, 0],
        "cmd_cap_v": [0x20, 0],
        "command": [0x10, 0],
        "imp_st_att": [0x10, 1],
        "sa_cap_v": [0x20, 2],
        "set_att": [0x10, 2],
        "ga_cap_v": [0x20, 3],
        "get_att": [0x10, 3],
    }

    # OSD response integrity check value sense data descriptor
    _osd_respnd_integrity_ckval_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "response_integrity_check_value": [0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 2],
    }
    # OSD attribute identification sense data descriptor
    _osd_attr_ident_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
    }

    # OSD sense data attribute descriptor
    _osd_sdata_attr_desc_bits = {
        "attribute_page": [0xFFFFFFFF, 0],
        "attribute_number": [0xFFFFFFFF, 4],
    }

    # ATA status return descriptor
    _ata_status_return_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "extend": [0x01, 2],
        "error": [0xFF, 3],
        "count_15_8": [0xFF, 4],
        "count_7_0": [0xFF, 5],
        "lba_31_24": [0xFF, 6],
        "lba_7_0": [0xFF, 7],
        "lba_39_32": [0xFF, 8],
        "lba_15_8": [0xFF, 9],
        "lba_47_40": [0xFF, 10],
        "lba_23_16": [0xFF, 11],
        "device": [0xFF, 12],
        "status": [0xFF, 13],
    }

    # another progress indication sense data descriptor
    _aprogress_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "another_sense_key": [0xFF, 2],
        "another_additional_sense_code": [0xFF, 3],
        "another_additional_sense_code_qualifier": [0xFF, 4],
        "another_progress_indication": [0xFFFF, 6],
    }

    # user data segment referral sense data descriptor
    _udata_segref_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "not_all_r": [0x01, 2],
    }

    # user data segment referral descriptor
    _udata_segref_desc_bits = {
        "number_of_trarget_port_group_descriptors": [0xFF, 3],
        "first_user_data_segment_lba": [0xFFFFFFFFFFFFFFFF, 4],
        "last_user_data_segment_lba": [0xFFFFFFFFFFFFFFFF, 12],
    }

    # target port group descriptor
    _tgt_pgroup_desc_bits = {
        "asymmetric_access_state": [0x0F, 0],
        "target_port_group": [0xFFFF, 2],
    }

    # forwarded sense data descriptor
    _fwd_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
        "fsdt": [0x80, 2],
        "sense_data_source": [0x0F, 2],
        "forwarded_status": [0xFF, 3],
    }

    # vendor specific sense data descriptors
    _vendor_sdata_desc_bits = {
        "desc_type": [0xFF, 0],
        "additional_len": [0xFF, 1],
    }

    # fixed format sense data
    _fixed_format_sdata_bits = {
        "valid": [0x80, 0],
        "response_code": [0x7F, 0],
        "filemark": [0x80, 2],
        "eom": [0x40, 2],
        "ili": [0x20, 2],
        "sdat_ovfl": [0x10, 2],
        "sense_key": [0x0F, 2],
        "information": [0xFFFFFFFF, 3],
        "additional_sense_len": [0xFF, 7],
        "command_specific_information": [0xFFFFFFFF, 8],
        "additional_sense_code": [0xFF, 12],
        "additional_sense_code_qualifier": [0xFF, 13],
        "field_replaceable_unit_code": [0xFF, 14],
        "sksv": [0x80, 15],
        "sense_key_specific_information": [0x7FFFFF, 15],
    }

    # descriptor format sense data
    _desc_format_sdata_bits = {
        "response_code": [0x7F, 0],
        "sdat_ovfl": [0x80, 4],
        "sense_key": [0x0F, 1],
        "additional_sense_code": [0xFF, 2],
        "additional_sense_code_qualifier": [0xFF, 3],
        "additional_sense_len": [0xFF, 7],
    }

    _descriptor_type_dict = {
        0x00: _info_sdata_desc_bits,
        0x01: _cmd_info_sdata_desc_bits,
        0x02: _skey_sdata_desc_bits,
        0x03: _fld_replace_unit_sdata_desc_bits,
        0x04: _stream_cmd_sdata_desc_bits,
        0x05: _blk_cmd_sdata_desc_bits,
        0x06: _osd_obj_ident_sdata_desc_bits,
        0x07: _osd_respnd_integrity_ckval_sdata_desc_bits,
        0x08: _osd_attr_ident_sdata_desc_bits,
        0x09: _ata_status_return_desc_bits,
        0x0A: _aprogress_sdata_desc_bits,
        0x0B: _udata_segref_sdata_desc_bits,
        0x0C: _fwd_sdata_desc_bits,
        0x80: _vendor_sdata_desc_bits,
    }

    def __init__(self, sense, print_data=False):
        self.valid = sense[0] & 0x80
        self.response_code = sense[0] & 0x7F
        self.data = {}
        self.show_data = print_data

        if self.response_code == SENSE_FORMAT_CURRENT_FIXED:
            self.data = self.unmarshall_fixed_format_sense_data(sense)
            self.asc = self.data["additional_sense_code"]
            self.ascq = self.data["additional_sense_code_qualifier"]
        elif self.response_code == SENSE_FORMAT_CURRENT_DESCRIPTOR:
            self.data = self.unmarshall_desc_format_sense_data(sense)
            self.asc = self.data["additional_sense_code"]
            self.ascq = self.data["additional_sense_code_qualifier"]

    def _ascq(self):
        return (self.asc << 8) + self.ascq

    def _describe_ascq(self):
        if self.asc in vendor_specific_sense_asc:
            return "Vendor specific ASC"
        if self.ascq in vendor_specific_sense_ascq:
            return "Vendor specific ASCQ"
        return sense_ascq_dict[self._ascq()]

    def __str__(self):
        if self.show_data:
            self.print_data()

        return "Check Condition: %s(0x%02X) ASC+Q:%s(0x%04X)" % (
            sense_key_dict[self.data["sense_key"]],
            self.data["sense_key"],
            self._describe_ascq(),
            self._ascq(),
        )

    def print_data(self):
        for k, v in self.data.items():
            print("%s -> 0x%02X" % (k, v))

    @staticmethod
    def unmarshall_fixed_format_sense_data(data):
        result = {}
        decode_bits(data, SCSICheckCondition._fixed_format_sdata_bits, result)
        return result

    @staticmethod
    def unmarshall_desc_format_sense_data(data):
        result = {}
        decode_bits(data, SCSICheckCondition._desc_format_sdata_bits, result)
        return result
